#Copyright Ken Faulkner 2007.
import sys
import wx
from Common.logRoutine import *
import traceback
from Datatypes.AudioDetails import AudioDetails
from Framework.GUI.CheckListCtrl import CheckListCtrl

#----------------------------------------------------------------------

    

class ListPanel( wx.Panel ):

  # map status to colours.
  statusColours = { AudioDetails.STATUS_DOWNLOADING: "BLUE",
                    AudioDetails.STATUS_START_DOWNLOAD: "BLUE",
                    AudioDetails.STATUS_DOWNLOADED: "GREEN",
                    AudioDetails.STATUS_COMPLETELY_FINISHED: "GREEN",
                    AudioDetails.STATUS_FOUND_IN_SEARCH: "RED",
                    AudioDetails.STATUS_ERROR: 'INDIAN RED' }

  default_colour = "BLACK"
                    
  def __init__(self, parent, detail_panel):
    wx.Panel.__init__(self, parent, -1)

    self.log = getLogger()
    self.detail_panel = detail_panel
    self.parent = parent
    self.list = CheckListCtrl( self )
    
    sizer = wx.BoxSizer()
    sizer.Add(self.list, 1, wx.EXPAND)
    self.SetSizer(sizer)

    # set the font.
    font = wx.Font(13, wx.SWISS, wx.NORMAL, wx.NORMAL)
    self.SetFont( font )

    self.list.InsertColumn(0, "Title")
    self.list.InsertColumn(1, "Downloaded")
    
    self.list.SetColumnWidth(0, 350 )
    self.list.SetColumnWidth(1, 150 )

    self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected, self.list)
    self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.on_item_deselected, self.list)

    self.item_list = []

  def on_check_item(self, index, flag):
    """
    Gets called by CheckListCtrl when item selected.
    """
    self.log.info("ListPanel::on_check_item start") 
    
    try:
      self.parent.on_check_item( index, flag )
      
    except:
      self.log.error("ListPanel::on_check_item ex " + traceback.format_exc() )
  
    
  def get_colour_for_item( self, item ):
    """
    Look at the item and the various status's within it, and determine the appropriate colour for it.
    What takes priority.... downloaded, or in current search...  etc....
    
    DOWNLOADED: Green.  Most important.
    DOWNLOADING: Blue.  next.
    FOUND IN SEARCH: RED. 
    other: BLACK
    """

    # default colour.    
    colour = "BLACK"
    
    # yes, entire if structure could probably go away, but need to revisit this.
    # This used to have 3 different status's but have converted to a single item.status
    # need to make sure things haven't barfed.
    if 1:
     if item.status == AudioDetails.STATUS_DOWNLOADED:
       colour = ListPanel.statusColours.get( item.status, ListPanel.default_colour )
     else:
       if item.status == AudioDetails.STATUS_START_DOWNLOAD or item.status == AudioDetails.STATUS_DOWNLOADING:
         colour = ListPanel.statusColours.get( item.status, ListPanel.default_colour )
       
       else:
         if item.status == AudioDetails.STATUS_FOUND_IN_SEARCH:
           colour = ListPanel.statusColours.get( item.status, ListPanel.default_colour )  
          
    colour = ListPanel.statusColours.get( item.status, ListPanel.default_colour )  
    #self.log.debug("colour is " + colour )
        
    colour = wx.NamedColour( colour )
    
    return colour

  def update_single_item(self, item ):
    """
    Populate list with info from bbc.
    """

    self.log.info("ListPanel::update_single_item")
    try:

      no_items = self.list.GetItemCount()
      
      self.log.debug("no items " + str( no_items ) )
      
      self.log.debug("display item " + item.title + " : " +item.description  )
     
      item_found = False

      # internal title v's UI title are a little diff (ep no's)
      title = item.title
      if item.episode_no != 0:
        title += "  : ep " + str( item.episode_no )
      
      orig_item = ""
      orig_item_title = ""
      
      i = 0
      
      for i in xrange( no_items ):
        # get col 0 for each item
        orig_item = self.list.GetItem( i )
        orig_item_title = self.list.GetItem( i, 0 ).GetText()
        desc = self.parent.item_list[ i ].description

      
        if orig_item_title == title:
     
          if desc == item.description:
            self.log.debug("DESC " + desc )

            item_found = True
            self.log.debug("ITEM no " + str( i ) )
          
            break
      
      if not item_found:
        i = self.list.InsertStringItem( 100000 , title )
          
        self.log.debug("created entry " + str(i) )
        
      percent = item.percent_complete
      if percent == None:
        percent = 0.0
      
      # just to make the UI look nice.
      percent = min( 100.0, percent )
        
      self.list.SetStringItem( i, 1, "%02d"%( percent )+"%" )
      
      
      colour = self.get_colour_for_item( item )
      it = self.list.GetItem( i )
      it.SetTextColour( colour ) 
      self.list.SetItem( it )

      if item.checked_for_download :
          self.list.CheckItem( i )
                  
    except:
      self.log.error("ListPanel::update_single_item ex " + traceback.format_exc() )
          
          
  def populate_list_new_and_not_working_yet(self ):
    """
    Populate list with info from bbc.
    """

    self.log.info("ListPanel::populate_list")
    try:

      # get local reference to item list from parent
      item_list = self.parent.item_list
      
      # guessing this is to clear it.
      # This sucks, need to find a better way.
      self.list.DeleteAllItems()
      
      for item in item_list:
        
        self.update_single_item( item )
        

        
      self.list.UpdateWindowUI()

    except:
      self.log.error("ListPanel::populate_list ex " + traceback.format_exc() )



  def populate_list(self ):
    """
    Populate list with info from bbc.
    Colours entries as per their status.
    Also marks items for download where the user has already downloaded other episodes of show.
    """

    self.log.info("ListPanel::populate_list")
    try:

      # list of titles that we've already partially downloaded.
      titles_downloaded = []
      
      # get local reference to item list from parent
      item_list = self.parent.item_list
      
      # guessing this is to clear it.
      # This sucks, need to find a better way.
      self.list.DeleteAllItems()
      
      
      # make a quick list of titles we've downloaded parts of     
      for item in item_list:
      
        # if downloaded, then add to titles we've already downloaded.
        if item.status == AudioDetails.STATUS_COMPLETELY_FINISHED:
          if item.title not in titles_downloaded:
            titles_downloaded.append( item.title )
        
      
      for item in item_list:
        
        title = item.title
        if item.episode_no != 0:
          title += "  : ep " + str( item.episode_no )
        
          
        idx = self.list.InsertStringItem(sys.maxint, title )
        colour = self.get_colour_for_item( item )
        
        i = self.list.GetItem( idx )
        i.SetTextColour( colour ) 
        self.list.SetItem( i )

        percent = item.percent_complete
        if percent == None:
          percent = 0.0
          
        percent = min(100.0, percent)
          
        self.list.SetStringItem( idx, 1, "%02d"%( percent )+"%" )
        
        if item.checked_for_download :
           self.list.CheckItem( idx )

        # we've not downloaded this particular item,  but see if the title is something we're interested in.
        # this is definitely not a fail safe way of doing this... but hey, will see if it works.
        if item.status !=  AudioDetails.STATUS_COMPLETELY_FINISHED:
          if item.title in titles_downloaded:
            self.list.CheckItem( idx )
        
      self.list.UpdateWindowUI()

    except:
      self.log.error("ListPanel::populate_list ex " + traceback.format_exc() )

    
  def on_item_selected(self, evt):
  
    self.log.debug("selecting index " + str( evt.m_itemIndex )  )
    
    title = self.parent.item_list[ evt.m_itemIndex].description
    self.log.debug("desc " + title )
    
    self.detail_panel.Clear()
    self.detail_panel.WriteText( title )

    
  def on_item_deselected(self, evt):
    self.log.debug('item deselected: %s\n' % evt.m_itemIndex)
    
